home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
lisp
/
kcl
/
akcl
/
kcl.lha
/
c
/
num_sfun.c
< prev
next >
Wrap
C/C++ Source or Header
|
1987-06-04
|
10KB
|
545 lines
/*
(c) Copyright Taiichi Yuasa and Masami Hagiya, 1984. All rights reserved.
Copying of this file is authorized to users who have executed the true and
proper "License Agreement for Kyoto Common LISP" with SIGLISP.
*/
#include "include.h"
#include "num_include.h"
object imag_unit, minus_imag_unit, imag_two;
int
fixnum_expt(x, y)
{
int z;
z = 1;
while (y > 0)
if (y%2 == 0) {
x *= x;
y /= 2;
} else {
z *= x;
--y;
}
return(z);
}
object
number_exp(x)
object x;
{
double exp();
switch (type_of(x)) {
case t_fixnum:
case t_bignum:
case t_ratio:
return(make_shortfloat((shortfloat)exp(number_to_double(x))));
case t_shortfloat:
return(make_shortfloat((shortfloat)exp((double)(sf(x)))));
case t_longfloat:
return(make_longfloat(exp(lf(x))));
case t_complex:
{
object y, y1;
object number_sin(), number_cos();
vs_mark;
y = x->cmp.cmp_imag;
x = x->cmp.cmp_real;
x = number_exp(x);
vs_push(x);
y1 = number_cos(y);
vs_push(y1);
y = number_sin(y);
vs_push(y);
y = make_complex(y1, y);
vs_push(y);
x = number_times(x, y);
vs_reset;
return(x);
}
default:
FEwrong_type_argument(Snumber, x);
}
}
object
number_expt(x, y)
object x, y;
{
enum type tx, ty;
object z, number_nlog();
vs_mark;
tx = type_of(x);
ty = type_of(y);
if (ty == t_fixnum && fix(y) == 0)
switch (tx) {
case t_fixnum: case t_bignum: case t_ratio:
return(small_fixnum(1));
case t_shortfloat:
return(make_shortfloat((shortfloat)1.0));
case t_longfloat:
return(make_longfloat(1.0));
case t_complex:
z = number_expt(x->cmp.cmp_real, y);
vs_push(z);
z = make_complex(z, small_fixnum(0));
vs_reset;
return(z);
default:
FEwrong_type_argument(Snumber, x);
}
if (number_zerop(x)) {
if (!number_plusp(ty==t_complex?y->cmp.cmp_real:y))
FEerror("Cannot raise zero to the power ~S.", 1, y);
return(number_times(x, y));
}
if (ty == t_fixnum || ty == t_bignum) {
if (number_minusp(y)) {
z = number_negate(y);
vs_push(z);
z = number_expt(x, z);
vs_push(z);
z = number_divide(small_fixnum(1), z);
vs_reset;
return(z);
}
z = small_fixnum(1);
vs_push(z);
vs_push(Cnil);
vs_push(Cnil);
while (number_plusp(y))
if (number_evenp(y)) {
x = number_times(x, x);
vs_top[-1] = x;
y = integer_divide1(y, small_fixnum(2));
vs_top[-2] = y;
} else {
z = number_times(z, x);
vs_top[-3] = z;
y = number_minus(y, small_fixnum(1));
vs_top[-2] = y;
}
vs_reset;
return(z);
}
z = number_nlog(x);
vs_push(z);
z = number_times(z, y);
vs_push(z);
z = number_exp(z);
vs_reset;
return(z);
}
object
number_nlog(x)
object x;
{
double log();
object r, i, a, p, number_sqrt(), number_atan2();
vs_mark;
if (type_of(x) == t_complex) {
r = x->cmp.cmp_real;
i = x->cmp.cmp_imag;
goto COMPLEX;
}
if (number_zerop(x))
FEerror("Zero is the logarithmic singularity.", 0);
if (number_minusp(x)) {
r = x;
i = small_fixnum(0);
goto COMPLEX;
}
switch (type_of(x)) {
case t_fixnum:
case t_bignum:
case t_ratio:
return(make_shortfloat((shortfloat)log(number_to_double(x))));
case t_shortfloat:
return(make_shortfloat((shortfloat)log((double)(sf(x)))));
case t_longfloat:
return(make_longfloat(log(lf(x))));
default:
FEwrong_type_argument(Snumber, x);
}
COMPLEX:
a = number_times(r, r);
vs_push(a);
p = number_times(i, i);
vs_push(p);
a = number_plus(a, p);
vs_push(a);
a = number_nlog(a);
vs_push(a);
a = number_divide(a, small_fixnum(2));
vs_push(a);
p = number_atan2(i, r);
vs_push(p);
x = make_complex(a, p);
vs_reset;
return(x);
}
object
number_log(x, y)
object x, y;
{
object z;
vs_mark;
if (number_zerop(y))
FEerror("Zero is the logarithmic singularity.", 0);
if (number_zerop(x))
return(number_times(x, y));
x = number_nlog(x);
vs_push(x);
y = number_nlog(y);
vs_push(y);
z = number_divide(y, x);
vs_reset;
return(z);
}
object
number_sqrt(x)
object x;
{
object z;
double sqrt();
vs_mark;
if (type_of(x) == t_complex)
goto COMPLEX;
if (number_minusp(x))
goto COMPLEX;
switch (type_of(x)) {
case t_fixnum:
case t_bignum:
case t_ratio:
return(make_shortfloat(
(shortfloat)sqrt(number_to_double(x))));
case t_shortfloat:
return(make_shortfloat((shortfloat)sqrt((double)(sf(x)))));
case t_longfloat:
return(make_longfloat(sqrt(lf(x))));
default:
FEwrong_type_argument(Snumber, x);
}
COMPLEX:
z = make_ratio(small_fixnum(1), small_fixnum(2));
vs_push(z);
z = number_expt(x, z);
vs_reset;
return(z);
}
object
number_atan2(y, x)
object y, x;
{
object z;
double atan(), dy, dx, dz;
dy = number_to_double(y);
dx = number_to_double(x);
if (dx > 0.0)
if (dy > 0.0)
dz = atan(dy / dx);
else if (dy == 0.0)
dz = 0.0;
else
dz = -atan(-dy / dx);
else if (dx == 0.0)
if (dy > 0.0)
dz = PI / 2.0;
else if (dy == 0.0)
FEerror("Logarithmic singularity.", 0);
else
dz = -PI / 2.0;
else
if (dy > 0.0)
dz = PI - atan(dy / -dx);
else if (dy == 0.0)
dz = PI;
else
dz = -PI + atan(-dy / -dx);
if (type_of(x) == t_longfloat || type_of(y) == t_longfloat)
z = make_longfloat(dz);
else
z = make_shortfloat((shortfloat)dz);
return(z);
}
object
number_atan(y)
object y;
{
object z, z1;
vs_mark;
if (type_of(y) == t_complex) {
z = number_times(imag_unit, y);
vs_push(z);
z = one_plus(z);
vs_push(z);
z1 = number_times(y, y);
vs_push(z1);
z1 = one_plus(z1);
vs_push(z1);
z1 = number_sqrt(z1);
vs_push(z1);
z = number_divide(z, z1);
vs_push(z);
z = number_nlog(z);
vs_push(z);
z = number_times(minus_imag_unit, z);
vs_reset;
return(z);
}
return(number_atan2(y, small_fixnum(1)));
}
object
number_sin(x)
object x;
{
double sin();
switch (type_of(x)) {
case t_fixnum:
case t_bignum:
case t_ratio:
return(make_shortfloat((shortfloat)sin(number_to_double(x))));
case t_shortfloat:
return(make_shortfloat((shortfloat)sin((double)(sf(x)))));
case t_longfloat:
return(make_longfloat(sin(lf(x))));
case t_complex:
{
object r;
object x0, x1, x2;
vs_mark;
x0 = number_times(imag_unit, x);
vs_push(x0);
x0 = number_exp(x0);
vs_push(x0);
x1 = number_times(minus_imag_unit, x);
vs_push(x1);
x1 = number_exp(x1);
vs_push(x1);
x2 = number_minus(x0, x1);
vs_push(x2);
r = number_divide(x2, imag_two);
vs_reset;
return(r);
}
default:
FEwrong_type_argument(Snumber, x);
}
}
object
number_cos(x)
object x;
{
double cos();
switch (type_of(x)) {
case t_fixnum:
case t_bignum:
case t_ratio:
return(make_shortfloat((shortfloat)cos(number_to_double(x))));
case t_shortfloat:
return(make_shortfloat((shortfloat)cos((double)(sf(x)))));
case t_longfloat:
return(make_longfloat(cos(lf(x))));
case t_complex:
{
object r;
object x0, x1, x2;
vs_mark;
x0 = number_times(imag_unit, x);
vs_push(x0);
x0 = number_exp(x0);
vs_push(x0);
x1 = number_times(minus_imag_unit, x);
vs_push(x1);
x1 = number_exp(x1);
vs_push(x1);
x2 = number_plus(x0, x1);
vs_push(x2);
r = number_divide(x2, small_fixnum(2));
vs_reset;
return(r);
}
default:
FEwrong_type_argument(Snumber, x);
}
}
object
number_tan(x)
object x;
{
object r, s, c;
vs_mark;
s = number_sin(x);
vs_push(s);
c = number_cos(x);
vs_push(c);
if (number_zerop(c) == TRUE)
FEerror("Cannot compute the tangent of ~S.", 1, x);
r = number_divide(s, c);
vs_reset;
return(r);
}
Lexp()
{
check_arg(1);
check_type_number(&vs_base[0]);
vs_base[0] = number_exp(vs_base[0]);
}
Lexpt()
{
check_arg(2);
check_type_number(&vs_base[0]);
check_type_number(&vs_base[1]);
vs_base[0] = number_expt(vs_base[0], vs_base[1]);
vs_pop;
}
Llog()
{
int narg;
narg = vs_top - vs_base;
if (narg < 1)
too_few_arguments();
else if (narg == 1) {
check_type_number(&vs_base[0]);
vs_base[0] = number_nlog(vs_base[0]);
} else if (narg == 2) {
check_type_number(&vs_base[0]);
check_type_number(&vs_base[1]);
vs_base[0] = number_log(vs_base[1], vs_base[0]);
vs_pop;
} else
too_many_arguments();
}
Lsqrt()
{
check_arg(1);
check_type_number(&vs_base[0]);
vs_base[0] = number_sqrt(vs_base[0]);
}
Lsin()
{
check_arg(1);
check_type_number(&vs_base[0]);
vs_base[0] = number_sin(vs_base[0]);
}
Lcos()
{
check_arg(1);
check_type_number(&vs_base[0]);
vs_base[0] = number_cos(vs_base[0]);
}
Ltan()
{
check_arg(1);
check_type_number(&vs_base[0]);
vs_base[0] = number_tan(vs_base[0]);
}
Latan()
{
int narg;
narg = vs_top - vs_base;
if (narg < 1)
too_few_arguments();
if (narg == 1) {
check_type_number(&vs_base[0]);
vs_base[0] = number_atan(vs_base[0]);
} else if (narg == 2) {
check_type_or_rational_float(&vs_base[0]);
check_type_or_rational_float(&vs_base[1]);
vs_base[0] = number_atan2(vs_base[0], vs_base[1]);
vs_pop;
} else
too_many_arguments();
}
init_num_sfun()
{
imag_unit
= make_complex(make_shortfloat((shortfloat)0.0),
make_shortfloat((shortfloat)1.0));
enter_mark_origin(&imag_unit);
minus_imag_unit
= make_complex(make_shortfloat((shortfloat)0.0),
make_shortfloat((shortfloat)-1.0));
enter_mark_origin(&minus_imag_unit);
imag_two
= make_complex(make_shortfloat((shortfloat)0.0),
make_shortfloat((shortfloat)2.0));
enter_mark_origin(&imag_two);
make_constant("PI", make_longfloat(PI));
make_function("EXP", Lexp);
make_function("EXPT", Lexpt);
make_function("LOG", Llog);
make_function("SQRT", Lsqrt);
make_function("SIN", Lsin);
make_function("COS", Lcos);
make_function("TAN", Ltan);
make_function("ATAN", Latan);
}